/**
 * 
 */
package edu.gtcfla.km.repositories.hibernate4;

import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import org.vsg.biz.BusinessEntityFactory;
import org.vsg.biz.utils.RepoInjectManager;
import org.vsg.common.orm.hibernate4.HibernateSessionManager;
import org.vsg.common.page.PaginationManager;
import org.vsg.search.api.page.PaginationException;

import edu.gtcfla.km.Knowledge;
import edu.gtcfla.km.model.KnowledgeD;
import edu.gtcfla.km.repositories.KnowledgeRepo;
import edu.gtcfla.km.repositories.page.KnowledgeCurrentUserPermProc;
import edu.gtcfla.km.repositories.page.KnowledgeCurrentUserProc;

/**
 * @author Bill Vison
 *
 */
@Repository
public class KnowledgeRepoImpl<T extends Knowledge, ID extends Serializable>  implements KnowledgeRepo<T, ID> {

	
	@Autowired
	private ApplicationContext ctx;
	
	@Autowired	
	private BusinessEntityFactory entityFactory;
	
	@Autowired(required=false)
	private PaginationManager paginationManager;

	private HibernateSessionManager sessionManager;

	private static final Logger logger = LoggerFactory.getLogger(KnowledgeRepoImpl.class);

	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		sessionManager = new HibernateSessionManager(sessionFactory);
	}		
	

	@Override
	public void save(T entity) {
		// TODO Auto-generated method stub
		Session session = sessionManager.getSession();
		
		if (entity instanceof KnowledgeD) {
			KnowledgeD domainD = (KnowledgeD)entity;

			ID id = (ID)session.save(domainD);
	
 			RepoInjectManager injectManager = new RepoInjectManager(ctx);		
			injectManager.injectSingle(entity);		
		}		
	}


	@Override
	public void update(T entity) {
		// TODO Auto-generated method stub
		Session session = sessionManager.getSession();
		
		if (entity instanceof KnowledgeD) {
			KnowledgeD domainD = (KnowledgeD)entity;

			session.update(session.merge(domainD));
	
			RepoInjectManager injectManager = new RepoInjectManager(ctx);		
			injectManager.injectSingle(entity);		
		}		
	}


	@Override
	public T findOne(ID primaryKey) {
		Session session = sessionManager.getSession();

		T entity = (T)session.load( KnowledgeD.class, primaryKey);
		RepoInjectManager injectManager = new RepoInjectManager(ctx);		
		injectManager.injectSingle(entity);	
		
		return entity;
	}


	@Override
	public Iterable<T> findAll() {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public Long count() {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public void deleteDirectly(T entity) {
		// TODO Auto-generated method stub
		Session session = sessionManager.getSession();
		session.delete( entity );
	}


	@Override
	public void deleteFully(T entity) {
		// TODO Auto-generated method stub
		Session sess = sessionManager.getSession();
		sess.delete( entity );		
	}


	@Override
	public void remove(T entity) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public boolean exists(ID primaryKey) {
		// TODO Auto-generated method stub
		return false;
	}


	@Override
	public Page<Knowledge> pageKnowledgeByCurrentUser(Pageable pageable , Set<String> cateIds) {
		
		
		
		KnowledgeCurrentUserProc proc = new KnowledgeCurrentUserProc();
		
		proc.setCateIds( cateIds );
		
		Page<Knowledge> page= null;
		try {
			page = paginationManager.createPage(pageable, proc);
		} catch (PaginationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return page;
	}


	@Override
	public Set<Knowledge> listKnowledgeByCategoryId(String categoryId) {
		
		StringBuffer query = new StringBuffer("select ");
		query.append("knowledge.id , knowledge.title , knowledge.shared , knowledge.releasedUserId , knowledge.releasedDate, ");
		query.append("knowledge.content , knowledge.keywords ");
		query.append("from ").append(KnowledgeD.class.getName() );
		query.append(" as knowledge ");
		query.append("left join knowledge.categoryD as cate ");	
	
		// -------------- get the condition for the query 
		query.append("where ");
		query.append("cate.id = :cateId ");

		if (logger.isInfoEnabled()) {
			logger.info("Execute SQL :"+query.toString());
		}
		
		Session session = sessionManager.getSession();
		Query hql = session.createQuery( query.toString() );
		hql.setString("cateId", categoryId);

		Iterator iter = hql.iterate();			
		Iterator dataIter = (Iterator)hql.iterate();

		Set dataList = new LinkedHashSet();		
		
		Object[] fields = null;
		while (dataIter.hasNext()) {
			fields = (Object[])dataIter.next();
			
			int i = 0;
			KnowledgeD kld = new KnowledgeD();
			kld.setId( (String)fields[i++] );
			kld.setTitle( (String)fields[i++] );
			kld.setShared( (Short)fields[i++] );
			kld.setReleasedUserId( (String)fields[i++] );
			kld.setReleasedDate( (Date)fields[i++] );
			
			kld.setContent( (String)fields[i++]  );
			kld.setKeywords( (String)fields[i++]  );
			
			dataList.add( kld );				
		}
		
		return dataList;
	}


	@Override
	public Page<Knowledge> pageKnowledgeByCurrentUser(Pageable pageable,
			Set<String> categoryIds, String currentUserId, String userGroupId) {
		// TODO Auto-generated method stub
		KnowledgeCurrentUserPermProc proc = new KnowledgeCurrentUserPermProc();
		
		proc.setCateIds( categoryIds );
		proc.setCurrentUserId( currentUserId );
		proc.setUserGroupId( userGroupId );
		
		Page<Knowledge> page= null;
		try {
			page = paginationManager.createPage(pageable, proc);
		} catch (PaginationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return page;
	}
	
	

	
}
